package de.gbeine.java.depview.beans;

import java.util.HashSet;
import java.util.Set;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Required;

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

import de.gbeine.java.depview.event.AddFilterEvent;
import de.gbeine.java.depview.event.ChangeGraphEvent;
import de.gbeine.java.depview.event.GraphLevelEvent;
import de.gbeine.java.depview.event.NewModelEvent;
import de.gbeine.java.depview.event.RemoveFilterEvent;
import de.gbeine.java.depview.graph.Filter;
import de.gbeine.java.depview.graph.GraphConverter;
import de.gbeine.java.depview.model.Package;

/**
 * The model converter create a graph from a model.
 */
@Slf4j
public final class ModelConverter {

    /**
     *
     */
    private final EventBus eventBus;

    /**
     *
     */
    private Set<Package> model = new HashSet<Package>();

    /**
     *
     */
    private Filter filter;

    private GraphConverter graphConverter = GraphConverter.DEFAULT_CONVERTER;

    /**
     *
     * @param pEventBus
     */
    public ModelConverter(final EventBus pEventBus) {
        this.eventBus = pEventBus;
    }

    /**
     *
     * @param pFilter
     */
    @Required
    public void setFilter(final Filter pFilter) {
        this.filter = pFilter;
    }

    /**
     *
     * @param pNewModelEvent
     */
    @Subscribe
    public void onNewModelEvent(final NewModelEvent pNewModelEvent) {
        ModelConverter.log.debug("Received new model event");
        this.model =  pNewModelEvent.getModel();
        this.processModel();
    }

    /**
     *
     * @param pAddFilterEvent
     */
    @Subscribe
    public void onAddFilterEvent(final AddFilterEvent pAddFilterEvent) {
        ModelConverter.log.debug("Received add filter event");
        this.filter.addFilter(pAddFilterEvent.getFilter());
        this.processModel();
    }

    /**
     *
     * @param pAddFilterEvent
     */
    @Subscribe
    public void onRemoveFilterEvent(final RemoveFilterEvent pRemoveFilterEvent) {
        ModelConverter.log.debug("Received remove filter event");
        this.filter.removeFilter(pRemoveFilterEvent.getFilter());
        this.processModel();
    }

    @Subscribe
    public void onGraphLevelEvent(final GraphLevelEvent pGraphLevelEvent) {
        ModelConverter.log.debug("Received graph level event");
        this.graphConverter = pGraphLevelEvent.getGraphConverter();
        this.processModel();
    }

    /**
     *
     */
    private void processModel() {
        final ChangeGraphEvent event = new ChangeGraphEvent(
            this,
            this.graphConverter.createGraph(this.model, this.filter)
        );
        this.eventBus.post(event);
    }
}
